import { defineComponent, reactive } from "vue";
import { ElButton, ElMessage, ElUpload, ElTooltip, ElLoading } from "element-plus";
import type { UploadFile } from "element-plus";
import { Workbook } from "exceljs";

import useCopy from "@/hook/useCopy";
import { downloadFile } from "@/utils";
import MonacoDditor from "@/components/Document/MonacoDditor/MonacoDditor.vue";

import cssModule from "./index.module.scss";

/** 状态类型 */
export type StateType = {
  /** json 字符串数据文本 */
  json: string;
  /** excel数据 */
  excelData: {
    /** excel 原始文件对象 */
    file: File | null;
    /** excel 原始工作表对象 */
    workbook: Workbook | null;
    /** 解析 excel 的数据 */
    workData: Record<string, any>;
  };
};

export default defineComponent({
  setup() {
    const state = reactive<StateType>({
      json: "",
      excelData: {
        file: null,
        workbook: null,
        workData: {}
      }
    });

    /** 文件改变 */
    const fileChange = async (uploadFile: UploadFile) => {
      const loading = ElLoading.service({
        lock: true,
        text: "解析数据中",
        background: "rgba(0, 0, 0, 0.7)"
      });
      state.excelData.file = uploadFile.raw || null;
      try {
        const workbook = new Workbook();
        const res = await workbook.xlsx.load(uploadFile.raw as any);
        state.excelData.workbook = res;
        const workData: StateType["excelData"]["workData"] = {};
        res.eachSheet(sheet => {
          const values = sheet.getSheetValues().filter(Boolean);
          // 取出表头
          const headers = values[0];
          if (headers && headers.length) {
            values.slice(1).forEach((e) => {
              const sheetValue: Record<string, any> = {};
              if (e && Array.isArray(e)) {
                e.forEach((val, idx) => {
                  // 表头作为key
                  const key = (headers as any)[idx];
                  if (key) sheetValue[key] = val;
                });
                if (Array.isArray(workData[sheet.name])) {
                  workData[sheet.name].push(sheetValue);
                } else {
                  workData[sheet.name] = [sheetValue];
                }
              }
            });
          } else {
            workData[sheet.name] = [];
          }
        });
        state.excelData.workData = workData;
        state.json = JSON.stringify(workData, null, 2);
      } catch (err) {
        console.log("err: ", err);
        ElMessage.error("excel解析失败: " + err);
      } finally {
        loading.close();
      }
    };

    /** 文件删除 */
    const fileRemove = () => {
      state.json = "";
      state.excelData.file = null;
      state.excelData.workbook = null;
      state.excelData.workData = {};
    };

    /** 生成 excel */
    const genExcel = async () => {
      const loading = ElLoading.service({
        lock: true,
        text: "生成excel中",
        background: "rgba(0, 0, 0, 0.7)"
      });
      try {
        const genExcelWorkData = JSON.parse(state.json);
        if (Array.isArray(genExcelWorkData) || !(genExcelWorkData instanceof Object)) {
          ElMessage.warning("生成的excel数据必须是对象并且不能是数组");
          return;
        }

        const genFileName = state.excelData.file?.name || "genExcel.xlsx";
        // TODO 这里的大小不能取源文件的大小
        const genFileSize = state.excelData.file?.size || 1;

        const workbook = new Workbook();
        for (const key in genExcelWorkData) {
          if (Object.prototype.hasOwnProperty.call(genExcelWorkData, key)) {
            const sheetData = genExcelWorkData[key];
            if (sheetData.length) {
              // 添加工作表
              const worksheet = workbook.addWorksheet(key);
              // 根据第一项生成表头
              const header = Object.keys(sheetData[0]);
              worksheet.columns = header.map(e => {
                return {
                  header: e,
                  key: e,
                  width: e.length * 5
                };
              });
              // 添加数据
              worksheet.addRows(sheetData);

              // 遍历行
              worksheet.eachRow((row, rowIdx) => {
                row.eachCell((cell) => {
                  if (rowIdx === 1) {
                    // 表头
                    cell.style = {
                      // 字体
                      font: {
                        bold: true,
                        color: { argb: "000000" }
                      },
                      // 填充
                      fill: {
                        type: "pattern",
                        pattern: "solid",
                        fgColor: { argb: "cccccc" }
                      },
                      // 居中
                      alignment: { vertical: "middle", horizontal: "center" },
                      // 边框
                      border: {
                        top: { style: "thin", color: { argb: "d4d4d4" } },
                        left: { style: "thin", color: { argb: "d4d4d4" } },
                        bottom: { style: "thin", color: { argb: "d4d4d4" } },
                        right: { style: "thin", color: { argb: "d4d4d4" } }
                      }
                    };
                  } else {
                    cell.style = {
                      alignment: { vertical: "middle", horizontal: "center" }
                    };
                  }
                });
              });
            }
          }
        }
        const arraybuffer = new ArrayBuffer(genFileSize);
        const buffer = await workbook.xlsx.writeBuffer(arraybuffer as any);
        downloadFile(buffer, genFileName);
      } catch (err) {
        console.log("err: ", err);
        ElMessage.error("excel生成失败: " + err);
      } finally {
        loading.close();
      }
    };

    return () => (
      <div class={cssModule.container}>
        <div style={{ maxWidth: "300px" }}>
          <ElUpload limit={1} auto-upload={false} accept=".xlsx,.xls" on-change={fileChange} on-remove={fileRemove}>
            <ElButton type="primary" size="default">
              选择文件
              <i class="iconfont icon-wendang" />
            </ElButton>
          </ElUpload>
        </div>
        {state.json && (
          <div class={cssModule["btn-container"]} style={{ marginBottom: "10px" }}>
            <ElButton type="primary" size="default" onClick={() => useCopy(state.json)}>
              复制
              <i class="iconfont icon-fuzhi" />
            </ElButton>

            <ElTooltip
              effect="dark"
              content="遍历对象以对象的 <b style='color:red;'>key</b> 作为工作表名<br />以数据第 <b style='color:red;'>1</b> 项的 <b style='color:red;'>key</b> 作为表头进行导出数据"
              placement="top"
              raw-content
            >
              <ElButton type="primary" size="default" onClick={() => genExcel()}>
                生成excel
                <i class="iconfont icon-baocun" />
              </ElButton>
            </ElTooltip>
          </div>
        )}
        <MonacoDditor v-model={state.json} height="84vh" language="json" />
      </div>
    );
  }
});
